package com.decorate.demo05;

import java.time.LocalDateTime;

/**
 *
 * 电子发票打印系统: 一张发票可以分为3个部分
 * 发票抬头: 顾客的名字,销售日期
 * 发票主体: 货物清单-商品名,数量,单价,小计
 * 发票结尾: 商品总金额
 * 发票头部和尾部可以有很多种可能的格式,因此系统的设计必须给出足够的灵活性,使得一个新的头部和尾部格式能够较为容易的插入到系统中.
 * 同时,本系统客户端必须可以随意地选择某一个头部格式和某一个尾部格式的组合并与主体部分格式结合起来.
 *
 * 为了使系统可以处理很多的头部格式和尾部格式的组合,采用装饰模式.
 * 装饰模式将更多功能动态地附加到一个对象上.对功能扩展而言,装饰模式提供了一个灵活的,可以替代继承的选择.
 * 在该系统中使用装饰模式,那么发票的头部和尾部都可以分别由具体装饰类HeaderDecorator 和具体装饰类 FootDecorator来代表.有多少头部和尾部,就可以有
 * 多少种相应的具体装饰类.这样一来,这些头部和尾部的组合就可以给出大量的选择.
 */
public class Client {
    private static Order order;

    /**
     * 首先，初始化客户的名称以及购买时间，然后添加两种不同的商品，最后先使用“发票尾”装饰发票，再使用“发票头”装饰发票
     */
    public static void main(String[] args) {
        order = new SalesOrder();//具体构建 - 发票

        order.setCustomerName("SANN");//发票中的客户名称
        order.setSalesDate(LocalDateTime.now());// 发票的日期

        //增加第一种商品
        OrderLine item = new OrderLine();
        item.setItemName("《简爱》");
        item.setUnits(4);
        item.setUnitPrice(25.0);
        order.addItem(item);

        //增加第二种商品
        OrderLine item2 = new OrderLine();
        item2.setItemName("《地球》");
        item2.setUnits(8);
        item2.setUnitPrice(19.0);
        order.addItem(item2);

//        order = new FooterDecorator(new HeaderDecorator(order));
        order = new HeaderDecorator(new FooterDecorator(order));
        // 打印发票
        order.print();

        /**
         * TODO 很好的案例,对于理解Java基础知识
         *
         * 1.父类 private 的属性子类也是有该属性的,private只是给程序开发人员不可直接调用,必须通过对外getter接口调用.
         *
         * 2.super.print() 和 super.order.print() 是不一样的. super.print()调用父类print方法, print方法内部调用的属性还是this对象自身的.
         * 而super.order.print()表示调用父类order的print方法,这样print方法内部调用的属性是order对象的,而非this对象自身的.
         *
         * 3.java中方法,比如print(),在输出时,输出的是对象自身的属性值.
         *
         */
    }
}
